package com.github.jameszbl.toolkits

import android.annotation.SuppressLint
import android.hardware.Camera
import android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE
import android.os.Bundle
import android.os.Environment
import android.os.Environment.DIRECTORY_PICTURES
import android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
import android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO
import android.util.Log
import android.view.KeyEvent
import android.widget.Button
import android.widget.FrameLayout
import android.widget.Toast
import android.widget.Toast.LENGTH_SHORT
import androidx.appcompat.app.AppCompatActivity
import com.github.jameszbl.toolkits.R.id.button_capture
import com.github.jameszbl.toolkits.R.id.camera_preview
import com.github.jameszbl.toolkits.R.layout.activity_camera
import java.io.File
import java.io.File.separator
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*


@Suppress("DEPRECATION")
class CameraActivity : AppCompatActivity() {

    private var mCameraId: Int = 0

    companion object {
        const val TAG = "Capture"
    }

    private var mCamera: Camera? = null
    private var mPreview: CameraPreview? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(activity_camera)
        initCamera()
        val captureButton: Button = findViewById(button_capture)
        captureButton.setOnClickListener {
            takePhoto()
        }
        val switchBtn: Button = findViewById(R.id.switch_camera)
        switchBtn.setOnClickListener {
            switchCamera()
            initCamera()
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && event?.action == KeyEvent.ACTION_DOWN) {
            takePhoto()
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    private fun takePhoto() {
        // get an image from the camera
        mCamera?.takePicture(null, null, mPicture)
        Toast.makeText(this, "Capture success", LENGTH_SHORT).show()
        onBackPressed()
    }

    private fun switchCamera() {
        if (0 == mCameraId) {
            mCameraId = 1
            Toast.makeText(this, "Switched to front camera", LENGTH_SHORT).show()
        } else {
            mCameraId = 0
            Toast.makeText(this, "Switched to back camera", LENGTH_SHORT).show()
        }
        initCamera()
    }

    private fun initCamera() {
        // Create an instance of Camera
        mCamera = getCameraInstance()
        mCamera?.setDisplayOrientation(90)
        //set camera to continually auto-focus
        if (0 == mCameraId) {
            val params = mCamera?.parameters
            params?.focusMode = FOCUS_MODE_CONTINUOUS_PICTURE
            mCamera?.parameters = params
        }

        mPreview = mCamera?.let {
            // Create our Preview view
            CameraPreview(this, it)
        }

        // Set the Preview view as the content of our activity.
        mPreview?.also {
            val preview: FrameLayout = findViewById(camera_preview)
            preview.addView(it)
        }
    }


    /**
     * A safe way to get an instance of the Camera object.
     */
    private fun getCameraInstance(): Camera? {
        return try {
            Camera.open(mCameraId) // attempt to get a Camera instance
        } catch (e: Exception) {
            // Camera is not available (in use or does not exist)
            null // returns null if camera is unavailable
        }
    }

    private val mPicture = Camera.PictureCallback { data, _ ->
        val pictureFile: File = getOutputMediaFile(MEDIA_TYPE_IMAGE) ?: run {
            Log.d(TAG, ("Error creating media file, check storage permissions"))
            return@PictureCallback
        }

        try {
            val fos = FileOutputStream(pictureFile)
            fos.write(data)
            fos.close()
        } catch (e: FileNotFoundException) {
            Log.d(TAG, "File not found: ${e.message}")
        } catch (e: IOException) {
            Log.d(TAG, "Error accessing file: ${e.message}")
        }
    }

    /**
     * Create a File for saving an image or video
     */
    @SuppressLint("SimpleDateFormat")
    private fun getOutputMediaFile(type: Int): File? {
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.

        val mediaStorageDir = File(
            Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES),
            "Toolkit"
        )
        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        mediaStorageDir.apply {
            if (!exists()) {
                if (!mkdirs()) {
                    Log.d("MyCameraApp", "failed to create directory")
                    return null
                }
            }
        }

        // Create a media file name
        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        return when (type) {
            MEDIA_TYPE_IMAGE -> {
                File("${mediaStorageDir.path}${separator}IMG_$timeStamp.jpg")
            }
            MEDIA_TYPE_VIDEO -> {
                File("${mediaStorageDir.path}${separator}VID_$timeStamp.mp4")
            }
            else -> null
        }
    }
}
